package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"go-web-learning/src/03_gin/04_restful/utils"
	"net/http"
	"sort"
	"strconv"
)

type ArticleModel struct {
	Id      int    `json:"id"`
	Title   string `json:"title"`
	Content string `json:"content"`
}

type Response struct {
	Code int    `json:"code"`
	Data any    `json:"data"`
	Msg  string `json:"msg"`
}

var (
	allArticles  map[int]ArticleModel
	articleMaxId int
)

func init() {
	allArticles = make(map[int]ArticleModel)
	allArticles[0] = ArticleModel{0, " GO语言入门", "这篇文章写了GO语言入门相关的内容"}
	allArticles[1] = ArticleModel{1, "GO语言进阶", "这篇文章写了GO语言进阶相关的内容"}
	allArticles[2] = ArticleModel{2, "GO语言大成", "这篇文章写了GO语言大成相关的内容"}
	articleMaxId = 2
}

func main() {
	router := gin.Default()
	router.GET("/articles", GetArticlesList)
	router.GET("/articles/:id", GetArticleDetail)
	router.POST("/articles", CreateArticles)
	router.PUT("/articles/:id", UpdateArticles)
	router.DELETE("/articles/:id", DeleteArticles)
	router.Run(":8080")
}

// GetArticlesList 文章列表
func GetArticlesList(c *gin.Context) {
	articleList := make([]ArticleModel, 0)
	for _, article := range allArticles {
		articleList = append(articleList, article)
	}
	sort.SliceStable(articleList, func(i int, j int) bool {
		return articleList[i].Id < articleList[j].Id
	})
	c.JSON(http.StatusOK, Response{Code: 0, Data: articleList, Msg: "success"})
}

// GetArticleDetail 文章详情
func GetArticleDetail(c *gin.Context) {
	articleIdStr := c.Param("id")
	articleId, err := strconv.Atoi(articleIdStr)
	if err != nil || articleId < 0 || articleId > articleMaxId {
		c.JSON(http.StatusOK, Response{Code: 500, Msg: fmt.Sprintf("no article id %s", articleIdStr)})
		return
	}
	c.JSON(http.StatusOK, Response{Code: 0, Data: allArticles[articleId], Msg: "success"})
}

// CreateArticles 创建文章
func CreateArticles(c *gin.Context) {
	body, _ := c.GetRawData()
	contentType := c.GetHeader("Content-Type")
	newArticle := ArticleModel{}
	err := utils.BindJson(body, contentType, &newArticle)
	response := Response{}
	if err != nil {
		response.Code = 500
		response.Msg = fmt.Sprintln("create article fail：", err)
	} else {
		articleMaxId += 1
		newArticle.Id = articleMaxId
		allArticles[newArticle.Id] = newArticle
		response.Code = 0
		response.Msg = "success"
	}
	c.JSON(http.StatusOK, response)
}

// UpdateArticles 更新文章
func UpdateArticles(c *gin.Context) {
	articleIdStr := c.Param("id")
	articleId, err := strconv.Atoi(articleIdStr)
	if err != nil || articleId < 0 || articleId > articleMaxId {
		c.JSON(http.StatusOK, Response{Code: 500, Msg: fmt.Sprintf("no article id %s", articleIdStr)})
		return
	}
	body, _ := c.GetRawData()
	contentType := c.GetHeader("Content-Type")
	newArticle := ArticleModel{}
	err = utils.BindJson(body, contentType, &newArticle)
	if err != nil {
		c.JSON(http.StatusOK, Response{Code: 500, Msg: fmt.Sprintln("get new article fail:", err)})
		return
	}
	newArticle.Id = articleId
	allArticles[articleId] = newArticle
	c.JSON(http.StatusOK, Response{Code: 0, Msg: "success"})
}

// DeleteArticles 删除文章
func DeleteArticles(c *gin.Context) {
	articleIdStr := c.Param("id")
	articleId, err := strconv.Atoi(articleIdStr)
	if err != nil {
		c.JSON(http.StatusOK, Response{Code: 500, Msg: fmt.Sprintf("no article id %s", articleIdStr)})
		return
	}
	delete(allArticles, articleId)
	c.JSON(http.StatusOK, Response{Code: 0, Msg: "success"})
}
